Skip to content

fix(codex): preserve sequential reasoning summaries#5233

Merged
can1357 merged 1 commit into
can1357:mainfrom
riverpilot:fix/codex-reasoning-summary-deltas
Jul 14, 2026
Merged

fix(codex): preserve sequential reasoning summaries#5233
can1357 merged 1 commit into
can1357:mainfrom
riverpilot:fix/codex-reasoning-summary-deltas

Conversation

@riverpilot

Copy link
Copy Markdown
Contributor

Summary

  • Preserve Codex reasoning-summary deltas when sequential-cutoff delivery is requested.
  • Prefer atomic .done summaries when available and flush buffered deltas at output-item completion.
  • Add regression coverage for delta-only sequential delivery.

Screenshots

No visual change.

Testing

  • bun test packages/ai/test/openai-codex-responses-lite.test.ts packages/ai/test/openai-codex-stream.test.ts packages/ai/test/openai-codex.test.ts
  • bun run --cwd=packages/ai check:types
  • Live OMP Codex smoke with --print-thoughts completed in the source worktree.

Risk

  • Limited to Codex reasoning-summary stream assembly.
  • Does not expose private raw chain-of-thought; it preserves summaries emitted by the API.

Notes

  • OMP continues requesting reasoning.summary = "detailed" when thinking is enabled.

AI Review Report

The change is narrowly scoped to sequential summary event delivery and includes a delta-only regression test.

Security Audit

No authentication, authorization, secret handling, or external request policy changes.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@github-actions github-actions Bot added the vouched Passed the vouch gate label Jul 11, 2026
@can1357 can1357 merged commit fedcd2a into can1357:main Jul 14, 2026
20 checks passed
@roboomp roboomp added fix provider:openai Provider-specific issues for openai providers LLM provider-specific issues review:p3 triaged labels Jul 14, 2026

@roboomp roboomp left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 — already merged: fedcd2a8781 merged #5233 into main, so there is no pending merge decision.
Two correctness regressions remain in the merged implementation: the standard text.done → part.done sequence adds a trailing blank thinking_delta, and a fallback-only item followed by an atomic item replays earlier summary text. The focused test passes but omits both sequences; the package changelog entry is also missing.
Thanks for the focused fix and regression coverage, @riverpilot.

Comment on lines 1846 to +1849
if (eventType === "response.reasoning_summary_part.done") {
if (this.#sequentialCutoffSummaries) return firstTokenTime;
if (this.runtime.currentItem?.type === "reasoning" && this.runtime.currentBlock?.type === "thinking") {
appendReasoningSummaryPartDone(
this.runtime.currentItem,
this.runtime.currentBlock,
stream,
output,
output.content.length - 1,
);
const entry = this.runtime.openItemForEvent(rawEvent);
if (this.#sequentialCutoffSummaries) {
this.runtime.queueSummaryDelta(entry, "\n\n");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking: response.reasoning_summary_part.done normally follows response.reasoning_summary_text.done (the repo's Responses server emits that exact order at openai-responses-server.ts:1114-1125). The text-done branch has already discarded the legacy deltas and emitted the atomic text, but this line then buffers a separator that #flushSummaryDeltas() emits at item completion. A standard delta("IGNORED") → text.done("Plan") → part.done → output_item.done stream therefore produces thinking_deltas ["Plan", "\n\n"] and final thinking "Plan\n\n", so atomic delivery is not actually authoritative. Please only queue the separator for an entry that has not received an atomic done, and cover the real event order in the regression test.

Comment on lines +1948 to +1950
#flushSummaryDeltas(entry: CodexOpenItem | null): void {
if (entry?.block?.type !== "thinking") return;
for (const delta of this.runtime.takeSummaryDeltas(entry)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking: This flush updates only the current block; it does not advance the response-global cutoffSummaries.emitted/summary state. If item 1 falls back to buffered delta "Plan" and item 2 later supplies atomic cumulative summaries "Plan" and "Plan\n\nInspect", item 2 re-emits the first section: the resulting thinking blocks are ["Plan", "Plan\n\nInspect"]. That violates the existing cross-item replay-dedup contract. Please fold fallback text into the global cutoff state (or otherwise reconcile it before later .done events) and add a mixed fallback/atomic regression case.

Comment on lines +694 to +695
/** Summary deltas buffered while waiting to see whether atomic `.done` events arrive. */
pendingSummaryDeltas = new Map<CodexOpenItem, string[]>();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should-fix: This changes observable Codex stream assembly in packages/ai, but the two-file PR omits the required packages/ai/CHANGELOG.md entry under ## [Unreleased]### Fixed. Please record the user-visible fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix provider:openai Provider-specific issues for openai providers LLM provider-specific issues review:p3 triaged vouched Passed the vouch gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants